unit TestDORMMapping.CoC;

interface

uses
  TestFramework,
  Generics.Collections,
  Rtti,
  dorm.Mappings.Strategies;

{$RTTI EXPLICIT
  FIELDS([vcPrivate, vcProtected, vcPublic, vcPublished])
  METHODS([vcPrivate, vcProtected, vcPublic, vcPublished])
  PROPERTIES([vcPrivate, vcProtected, vcPublic, vcPublished])}

type
  TCocMappingStrategyTests = class(TTestCase)
  private
    FMapping: IMappingStrategy;
    FContext: TRttiContext;
  protected
    procedure SetUp; override;
    procedure TearDown; override;
  published
    procedure TestGetMappingEntity_EmailCoC;
    procedure TestGetMappingEntity_PersonCoC;
    procedure TestGetMappingEntity_PhoneCoC;

    procedure TestGetMappingFields_EmailCoC;
    procedure TestGetMappingFields_PersonCoC;
    procedure TestGetMappingFields_PhoneCoC;

    procedure TestGetMappingPersonHasOneCar;
    procedure TestGetMappingPersonHasOneEmail;

    procedure TestGetMappingPersonHasManyPhones;
  end;

implementation

uses
  Classes,
  dorm.Mappings;

type
  TPersonCoC = class;

  TPhoneCoC = class
  private
    FNumber: string;
    FModel: string;
    FID: Integer;
    FPersonID: Integer;
    // Private!!!
    property PersonID: Integer read FPersonID write FPersonID;
  public
    property ID: Integer read FID write FID;
    property Number: string read FNumber write FNumber;
    property Model: string read FModel write FModel;
  end;

{$IF CompilerVersion >= 23}
  TPhonesCoC = class(TObjectList<TPhoneCoC>)
{$ELSE}
  TPhonesCoC = class(TdormObjectList<TPhoneCoC>)
{$IFEND}
  end;

  TCarCoC = class
  private
    FModel: string;
    FBrand: string;
    FPersonID: Integer;
    FID: Integer;
    FOwner: TPersonCoC;
    // Private!!!
    property PersonID: Integer read FPersonID write FPersonID;
  public
    property ID: Integer read FID write FID;
    property Brand: string read FBrand write FBrand;
    property Model: string read FModel write FModel;
    property Owner: TPersonCoC read FOwner write FOwner;
  end;

  TEmailCoC = class
  private
    FValue: string;
    FPersonID: Integer;
    FID: Integer;
    // Private!!!
    property PersonID: Integer read FPersonID write FPersonID;
  public
    property ID: Integer read FID write FID;
    property Value: string read FValue write FValue;
  end;

  TPersonCoC = class
  private
    FLastName: string;
    FAge: Int32;
    FFirstName: string;
    FID: Integer;
    FBornDate: TDate;
    FPhones: TPhonesCoC;
    FCar: TCarCoC;
    FEmail: TEmailCoC;
    FBornTimeStamp: TDateTime;
    FPhoto: TStream;
    function GetFullName: string;
  public
    property ID: Integer read FID write FID;
    property FirstName: string read FFirstName write FFirstName;
    property LastName: string read FLastName write FLastName;
    property Age: Int32 read FAge write FAge;
    property BornDate: TDate read FBornDate write FBornDate;
    property BornTimeStamp: TDateTime read FBornTimeStamp write FBornTimeStamp;
    property Photo: TStream read FPhoto write FPhoto;
    property Phones: TPhonesCoC read FPhones;
    property Car: TCarCoC read FCar write FCar;
    property Email: TEmailCoC read FEmail write FEmail;
    [Transient]
    property FullName: string read GetFullName;
  end;

{ TPersonCoC }

function TPersonCoC.GetFullName: string;
begin
  // Fake
end;

{ TCocMappingStrategyTests }

procedure TCocMappingStrategyTests.SetUp;
begin
  inherited;
  FContext := TRttiContext.Create;
  FMapping := TCoCMappingStrategy.Create;
end;

procedure TCocMappingStrategyTests.TearDown;
begin
  inherited;
  FMapping := nil;
  FContext.Free;
end;

procedure TCoCMappingStrategyTests.TestGetMappingEntity_EmailCoC;
var
  _Table: TMappingTable;
begin
  _Table := TMappingTable.Create;
  try
    FMapping.GetMapping(FContext.GetType(TEmailCoC), _Table);
    CheckEquals('EMAILCOC', _Table.TableName);
    CheckEquals('TestDORMMapping.CoC', _Table.Package);
    CheckEquals(3, _Table.Fields.Count);
    CheckEquals(0, _Table.HasOneList.Count);
    CheckEquals(0, _Table.HasManyList.Count);
    CheckEquals(0, _Table.BelongsToList.Count);
  finally
    _Table.Free;
  end;
end;

procedure TCoCMappingStrategyTests.TestGetMappingEntity_PersonCoC;
var
  _Table: TMappingTable;
begin
  _Table := TMappingTable.Create;
  try
    FMapping.GetMapping(FContext.GetType(TPersonCoC), _Table);
    CheckEquals('PERSONCOC', _Table.TableName);
    CheckEquals('TestDORMMapping.CoC', _Table.Package);
    CheckEquals(7, _Table.Fields.Count);
    CheckEquals(2, _Table.HasOneList.Count);
    CheckEquals(1, _Table.HasManyList.Count);
    CheckEquals(0, _Table.BelongsToList.Count);
  finally
    _Table.Free;
  end;
end;

procedure TCoCMappingStrategyTests.TestGetMappingEntity_PhoneCoC;
var
  _Table: TMappingTable;
begin
  _Table := TMappingTable.Create;
  try
    FMapping.GetMapping(FContext.GetType(TPhoneCoC), _Table);
    CheckEquals('PHONECOC', _Table.TableName);
    CheckEquals('TestDORMMapping.CoC', _Table.Package);
    CheckEquals(4, _Table.Fields.Count);
    CheckEquals(0, _Table.HasOneList.Count);
    CheckEquals(0, _Table.HasManyList.Count);
    CheckEquals(0, _Table.BelongsToList.Count);
  finally
    _Table.Free;
  end;
end;

procedure TCoCMappingStrategyTests.TestGetMappingFields_EmailCoC;
var
  _Table: TMappingTable;
  _Field: TMappingField;
begin
  _Table := TMappingTable.Create;
  try
    FMapping.GetMapping(FContext.GetType(TEmailCoC), _Table);

    _Field := _Table.FindByName('ID');
    CheckNotNull(_Field, 'TEmailCoC should be have property ID');
    CheckTrue(_Field.IsPK, 'TEmailCoC.Id should be a primary key');
    CheckEquals('ID', _Field.FieldName);
    CheckEquals('integer', _Field.FieldType);
    CheckEquals(0, _Field.Size);
    CheckEquals(0, _Field.Precision);
    CheckEquals('', _Field.DefaultValue);

    _Field := _Table.FindByName('Value');
    CheckNotNull(_Field, 'TEmailCoC should be have property Value');
    CheckFalse(_Field.IsPK, 'TEmailCoC.Value should not be a primary key');
    CheckEquals('VALUE', _Field.FieldName);
    CheckEquals('string', _Field.FieldType);
    CheckEquals(0, _Field.Size);
    CheckEquals(0, _Field.Precision);
    CheckEquals('', _Field.DefaultValue);

  finally
    _Table.Free;
  end;
end;

procedure TCocMappingStrategyTests.TestGetMappingFields_PersonCoC;
var
  _Table: TMappingTable;
  _Field: TMappingField;
begin
  _Table := TMappingTable.Create;
  try
    FMapping.GetMapping(FContext.GetType(TPersonCoC), _Table);
    _Field := _Table.FindByName('ID');
    CheckNotNull(_Field, 'TPersonCoC should be have property ID');
    CheckTrue(_Field.IsPK, 'TPersonCoC.Id should be a primary key');
    CheckEquals('ID', _Field.FieldName);
    CheckEquals('integer', _Field.FieldType);
    CheckEquals(0, _Field.Size);
    CheckEquals(0, _Field.Precision);
    CheckEquals('', _Field.DefaultValue);

    _Field := _Table.FindByName('FirstName');
    CheckNotNull(_Field, 'TPersonCoC should be have property FirstName');
    CheckFalse(_Field.IsPK, 'TPersonCoC.FirstName should not be a primary key');
    CheckEquals('FIRSTNAME', _Field.FieldName);
    CheckEquals('string', _Field.FieldType);
    CheckEquals(0, _Field.Size);
    CheckEquals(0, _Field.Precision);
    CheckEquals('', _Field.DefaultValue);

    _Field := _Table.FindByName('LastName');
    CheckNotNull(_Field, 'TPersonCoC should be have property LastName');
    CheckFalse(_Field.IsPK, 'TPersonCoC.LastName should not be a primary key');
    CheckEquals('LASTNAME', _Field.FieldName);
    CheckEquals('string', _Field.FieldType);
    CheckEquals(0, _Field.Size);
    CheckEquals(0, _Field.Precision);
    CheckEquals('', _Field.DefaultValue);

    _Field := _Table.FindByName('Age');
    CheckNotNull(_Field, 'TPersonCoC should be have property AGE');
    CheckFalse(_Field.IsPK, 'TPersonCoC.Age should not be a primary key');
    CheckEquals('AGE', _Field.FieldName);
    CheckEquals('integer', _Field.FieldType);
    CheckEquals(0, _Field.Size);
    CheckEquals(0, _Field.Precision);
    CheckEquals('', _Field.DefaultValue);

    _Field := _Table.FindByName('BornDate');
    CheckNotNull(_Field, 'TPersonCoC should be have property BornDate');
    CheckFalse(_Field.IsPK, 'TPersonCoC.BornDate should not be a primary key');
    CheckEquals('BORNDATE', _Field.FieldName);
    CheckEquals('date', _Field.FieldType);
    CheckEquals(0, _Field.Size);
    CheckEquals(0, _Field.Precision);
    CheckEquals('', _Field.DefaultValue);

    _Field := _Table.FindByName('BornTimeStamp');
    CheckNotNull(_Field, 'TPersonCoC should be have property BornTimeStamp');
    CheckFalse(_Field.IsPK, 'TPersonCoC.BornTimeStamp should not be a primary key');
    CheckEquals('BORNTIMESTAMP', _Field.FieldName);
    CheckEquals('datetime', _Field.FieldType);
    CheckEquals(0, _Field.Size);
    CheckEquals(0, _Field.Precision);
    CheckEquals('', _Field.DefaultValue);

    _Field := _Table.FindByName('Photo');
    CheckNotNull(_Field, 'TPersonCoC should be have property Photo');
    CheckFalse(_Field.IsPK, 'TPersonCoC.Photo should not be a primary key');
    CheckEquals('PHOTO', _Field.FieldName);
    CheckEquals('blob', _Field.FieldType);
    CheckEquals(0, _Field.Size);
    CheckEquals(0, _Field.Precision);
    CheckEquals('', _Field.DefaultValue);

    CheckNull(_Table.FindByName('FullName'),
      'TPersonCoC.FullName should be a non persistent property');
  finally
    _Table.Free;
  end;
end;

procedure TCocMappingStrategyTests.TestGetMappingFields_PhoneCoC;
var
  _Table: TMappingTable;
  _Field: TMappingField;
begin
  _Table := TMappingTable.Create;
  try
    FMapping.GetMapping(FContext.GetType(TPhoneCoC), _Table);

    _Field := _Table.FindByName('ID');
    CheckNotNull(_Field, 'TPhoneCoC should be have property ID');
    CheckTrue(_Field.IsPK, 'TPhoneCoC.Id should be a primary key');
    CheckEquals('ID', _Field.FieldName);
    CheckEquals('integer', _Field.FieldType);
    CheckEquals(0, _Field.Size);
    CheckEquals(0, _Field.Precision);
    CheckEquals('', _Field.DefaultValue);

    _Field := _Table.FindByName('Number');
    CheckNotNull(_Field, 'TPhoneCoC should be have property Number');
    CheckFalse(_Field.IsPK, 'TPhoneCoC.Number should not be a primary key');
    CheckEquals('NUMBER', _Field.FieldName);
    CheckEquals('string', _Field.FieldType);
    CheckEquals(0, _Field.Size);
    CheckEquals(0, _Field.Precision);
    CheckEquals('', _Field.DefaultValue);

    _Field := _Table.FindByName('Model');
    CheckNotNull(_Field, 'TPhoneCoC should be have property Model');
    CheckFalse(_Field.IsPK, 'TPhoneCoC.Number should not be a primary key');
    CheckEquals('MODEL', _Field.FieldName);
    CheckEquals('string', _Field.FieldType);
    CheckEquals(0, _Field.Size);
    CheckEquals(0, _Field.Precision);
    CheckEquals('', _Field.DefaultValue);

  finally
    _Table.Free;
  end;
end;

procedure TCocMappingStrategyTests.TestGetMappingPersonHasOneCar;
var
  _Table: TMappingTable;
  _Relation: TMappingRelation;
begin
  _Table := TMappingTable.Create;
  try
    FMapping.GetMapping(FContext.GetType(TPersonCoC), _Table);
    _Relation := _Table.FindHasOneByName('Car');
    CheckNotNull(_Relation, 'TPersonCoC.Car property should be a HasOne relation');
    with _Relation do
    begin
      CheckEquals('TCarCoC', _Relation.ChildClassName);
      CheckEquals('PersonCoCID', _Relation.ChildFieldName);
      CheckFalse(_Relation.LazyLoad, 'TPersonCoC.Car should be not lazyload');
    end;
  finally
    _Table.Free;
  end;
end;

procedure TCocMappingStrategyTests.TestGetMappingPersonHasOneEmail;
var
  _Table: TMappingTable;
  _Relation: TMappingRelation;
begin
  _Table := TMappingTable.Create;
  try
    FMapping.GetMapping(FContext.GetType(TPersonCoC), _Table);
    _Relation := _Table.FindHasOneByName('Email');
    CheckNotNull(_Relation, 'TPersonCoC.Email property should be a HasOne relation');
    with _Relation do
    begin
      CheckEquals('TEmailCoC', _Relation.ChildClassName);
      CheckEquals('PersonCoCID', _Relation.ChildFieldName);
      CheckFalse(_Relation.LazyLoad, 'TPersonCoC.Email should be not lazyload');
    end;
  finally
    _Table.Free;
  end;
end;

procedure TCocMappingStrategyTests.TestGetMappingPersonHasManyPhones;
var
  _Table: TMappingTable;
  _Relation: TMappingRelation;
begin
  _Table := TMappingTable.Create;
  try
    FMapping.GetMapping(FContext.GetType(TPersonCoC), _Table);
    _Relation := _Table.FindHasManyByName('Phones');
    CheckNotNull(_Relation, 'TPersonCoC.Phones property should be a HasMany relation');
    with _Relation do
    begin
      CheckEquals('TPhoneCoC', _Relation.ChildClassName);
      CheckEquals('PersonCoCID', _Relation.ChildFieldName);
      CheckFalse(_Relation.LazyLoad, 'TPersonCoC.Phones should be not lazyload');
    end;
  finally
    _Table.Free;
  end;
end;

initialization
  RegisterTest(TCoCMappingStrategyTests.Suite);

end.
